#include "CCanRecordInfobase.h"
#include "clcomfuncs.h"

#define CANRECORDINFOBASE_ATTRIBUTE_PATH	"attri"
#define CANRECORDINFOBASE_SEQUENCE_PATH		"sequence"

void CCanRecordInfobase::Copy(CCanRecordInfobase* pdst,
	const CCanRecordInfobase* psrc)
{
	CAttribute::Copy(pdst->m_pAttribute, psrc->m_pAttribute);

	pdst->ReleaseSequence();

    map<CLComString, CLComSequence*>::const_iterator it = psrc->m_mapSequences.begin();
	for (; it != psrc->m_mapSequences.end(); ++it)
	{
		pdst->CreateSequence(it->first);

        CLComSequence::Copy(pdst->GetSequence(it->first), it->second);
	}
}

void CCanRecordInfobase::CopyAttributes(const CCanRecordInfobase* pSrc)
{
	CAttribute::Copy(m_pAttribute, pSrc->m_pAttribute);
}

void CCanRecordInfobase::CreateAttributePath()
{
	m_attPathName = m_PathName;
	m_attPathName += "\\";
	m_attPathName += CANRECORDINFOBASE_ATTRIBUTE_PATH;
	m_attPathName += "\\";

    CLComFuncs::Make_dir(m_attPathName);
}
void CCanRecordInfobase::CreateSequencePath()
{
	m_sePathName = m_PathName;
	m_sePathName += "\\";
	m_sePathName += CANRECORDINFOBASE_SEQUENCE_PATH;
	m_sePathName += "\\";

    CLComFuncs::Make_dir(m_sePathName);
}

CLComString CCanRecordInfobase::CreateMemberPath(CLComString path, CLComString pathName)
{
    CLComString resPath = path;
	resPath += "\\";
	resPath += pathName;
	resPath += "\\";

    CLComFuncs::Make_dir(resPath);
	
	return resPath;
}

CCanRecordInfobase::CCanRecordInfobase(CLComString pathName)
{
	m_PathName = pathName;
	//CreateSequencePath();
	//CreateAttributePath();
	m_sePathName = CreateMemberPath(m_PathName, CANRECORDINFOBASE_SEQUENCE_PATH);
	m_attPathName = CreateMemberPath(m_PathName, CANRECORDINFOBASE_ATTRIBUTE_PATH);

	m_pAttribute = new CAttribute(m_attPathName);
}
CCanRecordInfobase::~CCanRecordInfobase()
{
	Release();
}
void CCanRecordInfobase::Release()
{
	ReleaseAttribute();
	ReleaseSequence();
}
void CCanRecordInfobase::ReleaseAttribute()
{
	delete m_pAttribute;
	m_pAttribute = nullptr;
}
void CCanRecordInfobase::ReleaseSequence()
{
    map<CLComString, CLComSequence*>::iterator it = m_mapSequences.begin();
	for (; it != m_mapSequences.end(); ++it)
	{
		delete it->second;
		it->second = nullptr;
	}
	m_mapSequences.clear();
}

int CCanRecordInfobase::ModifyAttribute(CLComValue& item)
{
	int eRet = ERECORD_RETURN_VALUE_OK;

    lock_guard<mutex> lock(m_lockSetion);

	eRet = m_pAttribute->ModifyAttribute(item);

	return eRet;
}

int CCanRecordInfobase::ModifyAttributeInt(const CLComString& key, long long value)
{
    CLComValue item;
	item.SetKey(key.GetChars());
	item.SetIntValue(value);
	return ModifyAttribute(item);
}

int CCanRecordInfobase::ModifyAttributeString(const CLComString& key, const CLComString& value)
{
    CLComValue item;
	item.SetKey(key.GetChars());
	item.SetStringValue(value.GetChars());
	return ModifyAttribute(item);
}

int CCanRecordInfobase::ModifyAttributeDouble(const CLComString& key, double value)
{
    CLComValue item;
	item.SetKey(key.GetChars());
	item.SetDoubleValue(value);
	return ModifyAttribute(item);
}

int CCanRecordInfobase::ModifyAttributeObject(const CLComString& key, void* value, long long len)
{
    CLComValue item;
	item.SetKey(key.GetChars());
	item.SetObjValueDeep(value, len);
	return ModifyAttribute(item);
}

long long CCanRecordInfobase::GetAttributeInt(CLComString key)
{
    CLComValue item;
	item.SetKey(key.GetChars());
	GetAttribute(item);
	return item.GetIntValue();
}

CLComString CCanRecordInfobase::GetAttributeString(CLComString key)
{
    CLComValue item;
	item.SetKey(key.GetChars());
	GetAttribute(item);
	return item.GetStringValue();
}

double CCanRecordInfobase::GetAttributeDouble(CLComString key)
{
    CLComValue item;
	item.SetKey(key.GetChars());
	GetAttribute(item);
	return item.GetDoubleValue();
}

long long CCanRecordInfobase::GetAttributeObj(CLComString key, void** obj)
{
    CLComValue item;
	item.SetKey(key.GetChars());
	GetAttribute(item);
	*obj = item.GetPObject();
	return item.GetPObjectLen();
}

void CCanRecordInfobase::GetAttributes(map<string, CLComValue>& outAttributes)const
{
	m_pAttribute->GetAttributes(outAttributes);
}
int CCanRecordInfobase::GetAttribute(CLComValue& item)const
{
	return m_pAttribute->GetAttribute(item);
}
void CCanRecordInfobase::ClearAttributes()
{
	m_pAttribute->ClearAttributes();
}

void CCanRecordInfobase::LoadAttriFromFile(CLComString fileName)
{
    CLComString attrPath = CreateMemberPath(fileName, CANRECORDINFOBASE_ATTRIBUTE_PATH);
	m_pAttribute->LoadFromFile(attrPath);
}

void CCanRecordInfobase::LoadSequenceFromFile(CLComString fileName, CLComString seID)
{
    CLComString	seqPath = CreateMemberPath(fileName, CANRECORDINFOBASE_SEQUENCE_PATH);
    map<CLComString, CLComSequence*>::iterator it = m_mapSequences.find(seID);
	if (it == m_mapSequences.end())
	{
        m_mapSequences.insert(std::make_pair(seID, new CLComSequence(seID)));
	}
	m_mapSequences[seID]->LoadFromFile(seqPath);
}

 void CCanRecordInfobase::RegisterAttribute(CLComString key, ECLCOMVALUE_TYPE type)
{
     lock_guard<mutex> lock(m_lockSetion);

	 m_pAttribute->RegisterAttribute(key, type);
}

 bool CCanRecordInfobase::GoBackSe(CLComString seid, int nIndex)
 {
     CLComSequence* pSequence = GetSequence(seid);
	 if (pSequence)
	 {
		 return  pSequence->GoBack(nIndex);
	 }
	 return false;
 }

 bool CCanRecordInfobase::GoNextSe(CLComString seid, int nIndex)
 {
     CLComSequence* pSequence = GetSequence(seid);
	 if (pSequence)
	 {
		 return  pSequence->GoNext(nIndex);
	 }
	 return false;
 }
 int CCanRecordInfobase::BackUpSe(CLComString seid, CRecordItem& recordinfo)
 {
     CLComSequence* pSequence = GetSequence(seid);
	 if (pSequence)
	 {
		 return  pSequence->BackUp(recordinfo);
	 }
	 return false;
 }
 bool CCanRecordInfobase::GoBackAttribute(int nIndex)
 {
	return m_pAttribute->GoBack(nIndex);
 }
 bool CCanRecordInfobase::GoNextAttribute(int nIndex)
 {
	return m_pAttribute->GoNext(nIndex);
 }
 int CCanRecordInfobase::BackUpAttribute(CRecordItem& recordinfo)
 {
	return m_pAttribute->BackUp(recordinfo);
 }
 void CCanRecordInfobase::Update()
 {
	 m_pAttribute->Update();
	 
     map<CLComString, CLComSequence*>::iterator it = m_mapSequences.begin();
	 for (; it != m_mapSequences.end(); ++it)
	 {
		 it->second->Update();
	 }
 }

 void CCanRecordInfobase::ClearBackup()
 {
	 m_pAttribute->ClearBackup();
	 
     map<CLComString, CLComSequence*>::iterator it = m_mapSequences.begin();
	 for (; it != m_mapSequences.end(); ++it)
	 {
		 it->second->ClearBackup();
	 }
 }
 void CCanRecordInfobase::Save2File(FILE* file)
 {
	 m_pAttribute->Save2File(file);
	 
     map<CLComString, CLComSequence*>::iterator it = m_mapSequences.begin();
	 for (; it != m_mapSequences.end(); ++it)
	 {
		 it->second->Save2File(file);
	 }
 }

 CLComSequence* CCanRecordInfobase::GetSequence(CLComString key)
 {
     map<CLComString, CLComSequence*>::iterator it = m_mapSequences.find(key);
	 if (it != m_mapSequences.end())
	 {
		 return it->second;
	 }
	 return NULL;
 }
 void CCanRecordInfobase::CreateSequence(CLComString seID)
 {
	 if (!GetSequence(seID))
	 {
         CLComString tempstr = m_sePathName;
		 tempstr += "\\";
		 tempstr += seID;
		 tempstr += "\\";

         CLComFuncs::Make_dir(tempstr);

         CLComSequence* pse = new CLComSequence(tempstr);
		 m_mapSequences[seID] = pse;
	 }
 }

 void CCanRecordInfobase::AddItem(CLComString seid, CLComString id)
 {
     CLComSequence* pse = GetSequence(seid);
	 if (pse)
	 {
		 pse->AddItem(id);
	 }
 }
 CLComString CCanRecordInfobase::GetFirstItem(CLComString seid)
 {
     CLComSequence* pse = GetSequence(seid);
	 if (pse)
	 {
		 return pse->GetFirstItem();
	 }
	 return "";
 }
 CLComString CCanRecordInfobase::GetNextItem(CLComString seid,
     CLComString currentid)
 {
     CLComSequence* pse = GetSequence(seid);
	 if (pse)
	 {
		 return pse->GetNextItem(currentid);
	 }
	 return "";
 }

 CLComString CCanRecordInfobase::GetPrevItem(CLComString seid, CLComString currentid)
 {
     CLComSequence* pse = GetSequence(seid);
	 if (pse)
	 {
		 return pse->GetPrevItem(currentid);
	 }
	 return "";
 }

 int CCanRecordInfobase::InsertItemBack(CLComString seid, CLComString id, const CLComValue item, CLComString preID)
 {
     CLComSequence* pse = GetSequence(seid);
	 if (pse)
	 {
		 return pse->AddItemBack(id, item, preID);
	 }
	 return ERECORD_RETURN_VALUE_OK;
 }

 void CCanRecordInfobase::DelItem(CLComString seid, CLComString id)
 {
     CLComSequence* pse = GetSequence(seid);
	 if (pse)
	 {
		 pse->DelItem(id);
	 }
 }

 int CCanRecordInfobase::MoveUP(CLComString seid, CLComString currentid)
 {
     CLComSequence* pse = GetSequence(seid);
	 if (pse)
	 {
		 return pse->MoveUP(currentid);
	 }
	 return ERECORD_RETURN_VALUE_FALSE;
 }
 int CCanRecordInfobase::MoveDown(CLComString seid, CLComString currentid)
 {
     CLComSequence* pse = GetSequence(seid);
	 if (pse)
	 {
		 return pse->MoveDown(currentid);
	 }
	 return ERECORD_RETURN_VALUE_FALSE;
 }
 void CCanRecordInfobase::Move2Next(CLComString seid, CLComString frontID,
     CLComString currentid)
 {
     CLComSequence* pse = GetSequence(seid);
	 if (pse)
	 {
		 pse->Move2Next(frontID, currentid);
	 }
 }
 void CCanRecordInfobase::Move2Front(CLComString seid, CLComString nextID,
     CLComString currentid)
 {
     CLComSequence* pse = GetSequence(seid);
	 if (pse)
	 {
		 pse->Move2Front(nextID, currentid);
	 }
 }

 void CCanRecordInfobase::MoveUP(CLComString seid, CLComString startID,
     CLComString endID)
 {
     CLComSequence* pse = GetSequence(seid);
	 if (pse)
	 {
		 pse->MoveUP(startID, endID);
	 }
 }
 void CCanRecordInfobase::MoveDown(CLComString seid, CLComString startID,
     CLComString endID)
 {
     CLComSequence* pse = GetSequence(seid);
	 if (pse)
	 {
		 pse->MoveDown(startID, endID);
	 }
 }
 void CCanRecordInfobase::Move2Next(CLComString seid, CLComString frontID,
     CLComString startID, CLComString endID)
 {
     CLComSequence* pse = GetSequence(seid);
	 if (pse)
	 {
		 pse->Move2Next(frontID, startID, endID);
	 }
 }
 void CCanRecordInfobase::Move2Front(CLComString seid, CLComString nextID,
     CLComString startID, CLComString endID)
 {
     CLComSequence* pse = GetSequence(seid);
	 if (pse)
	 {
		 pse->Move2Front(nextID, startID, endID);
	 }
 }
